text:
Q: Efficient string reversal I want to compare the following two ways of reversing a string:
Version 1:
function reverseString(str){
  return str.split('').reverse().join('');
}

Version 2:
function reverseString(str){
  if(str.length == 1) return str;
  return str[str.length - 1] + (reverseString(str.slice(0,str.length - 1)));
}

How can I reliably determine which pattern is more efficient?

A: Based off of this jsperf, your first function (number 1) appears to perform quicker while testing on Chrome 73 with windows 10. It is worth noting that the difference computed here is negligible.
Note that you may create your own benchmarks using sites such as jsperf.

A: The recursive one seems a bit slower. I would suggest a third option: a simple for loop and string concatenation.
NB: the downside of the recursive solution is that it can run into a stack overflow when the string is long.
You can use benchmark.js to measure performance:

function reverseString1(str) {
    return str.split('').reverse().join('');
}
function reverseString2(str) {
    if (str.length == 1) return str;
    return str[str.length - 1] + (reverseString2(str.slice(0,str.length - 1)));
}
function reverseString3(str) {
    let result = "";
    for (let i = str.length; i--;) result += str[i];
    return result;
}

// An input string of 200 characters:
let str = "asirjsmpfuenndlsuegi".repeat(20);
console.log("Tests...");
const suite = new Benchmark.Suite("reverse string");
suite.add("split&join", () => reverseString1(str))
     .add(" recursive", () => reverseString2(str))
     .add("  for-loop", () => reverseString3(str))
     .on('cycle', (event) => console.log(String(event.target)))
     .on('complete', () =>
         console.log('Fastest is: ' + suite.filter('fastest').map('name')))
     .run({ 'async': true });
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.4/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/benchmark/2.1.4/benchmark.js"></script>

redpajama_set_name: RedPajamaStackExchange


Gertrud Lindsay, 87 of Tunnel City, passed away Monday, September 10, 2018 at her home.
Funeral services will be held at 11:00 A.M. Friday, September 14, 2018 at The Church of Jesus Christ of Latter-Day Saints, 702 E Montgomery St, Sparta. President Walter Rakow will officiate. Visitation will be one hour prior to services at the church. She will be laid to rest at Wood Cemetery, Town of Byron. Sonnenburg Family Funeral Home, Tomah has been entrusted with arrangements. Online condolences may be left at www.sonnenburgfamilyfh.com.


The indisputable prime responsibility of any government is to protect the life and limb of its citizens…writes Isi Leibler.
This overrides all other considerations, including civic rights and freedom of association and expression.
The world is currently facing the most severe global threat to Western civilisation since World War II when, despite enormous human cost, the free world ultimately united and defeated Nazism.
Under such circumstances and in the light of the current intensive new round of murders in Israel by crazed religious fanatics who stab, shoot and run down pedestrians, the Israeli government must now consider introducing what would previously have been considered draconian legislation to maximize security for its citizens.
It is certain that the U.S., U.K. or French government would act far more stringently if they faced Islamists within their ranks publicly calling for innocent civilians to be butchered.
Particularly another point, so as to protect its citizens Israel must deploy armed men on the ground to showing to the population on one hand a security climate and on the other hand, so as to disheartening terrorists to commit their programmed misdeeds by putting guards on the street throughout Israel.
Although most of your suggestions appear to be practical solutions, and might even make more citizens safer in the short term, would we not be losing more by adopting this type of solution? We should remember that draconian measures issued with the best of intentions too often backfire on those that wished them.
Each citizen lost to terrorist acts is a horrible personal disaster to friends and family, and every life and limb is sacred. We are fighting a war against those with oppressive reactionary beliefs, and there will be casualties, unfortunately mostly among non-combatants. But is this not the case in most wars?


text:
class Ezine::TestMember
  include SS::Document
  include SS::Reference::User
  include SS::Reference::Site
  include Cms::SitePermission
  include Ezine::MemberSearchable

  field :email, type: String
  field :email_type, type: String

  permit_params :email, :email_type

  belongs_to :node, class_name: "Cms::Node"

  validates :email, uniqueness: { scope: :node_id }, presence: true, email: true

  # Test member is always "enabled".
  scope :enabled, ->{ all }

  def email_type_options
    [
      [I18n.t('ezine.options.email_type.text'), 'text'],
      [I18n.t('ezine.options.email_type.html'), 'html'],
    ]
  end

  def test_member?
    true
  end
end

redpajama_set_name: RedPajamaGithub


You must filll out a Talent Show form and deliver it to Ms. Goodson in room 279. Space is limited, so first come, first served. All acts MUST BE APPROVED by Ms. Goodson before the show.
ALS ALLIANCE - this club is dedicated to raising money for Project ALS (https://www.projectals.org/ ) . Project ALS is an organization dedicated to finding a cure for brain-based diseases including: Amyotrophic Later Sclerosis, Parkinson's, Alzheimers and more.
In twenty years, Project ALS has advanced ALS research significantly, overseeing productive collaborations among 25 leading research institutions, the discovery of over 60 ALS genes, the development of the world's first patient based models of ALS for laboratory testing, supported and managed the first ever facility dedicated exclusively to ALS and stem cell research, and accelerated drug testing and clinical trials through the identification of new drug targets.


text:
Venice Design Biennial
We are glad to announce that the fourth edition will be supported by:
Main Sponsor: McArthurGlen - Noventa di Piave Designer Outlet
Design is not primarily made of objects, but of choices that influence the way of living, of dwelling, of relating to others.
The Venice Design Biennial brings to Venice designers from all over the world, while at the same time providing a platform for Venetian designers and design practices.
McArthurGlen - Noventa di Piave Designer Outlet, located in the mainland of Venice, is the place to go for both locals and international travellers looking for a wide choice of fashion and household design.
This new partnership for the 2023 edition aims to emphasise the plurality of design, so that it is a device for seeking one's own uniqueness.
Manufacturer and Editor: Vetralia
Active in the collectible design proposal, Vetralia is a meeting place for creatives, whose wish is to combine contemporary artistic forms with the multiple Venetian craftsmanship skills, expression of a culture of excellence that has its roots in the Renaissance workshop.
Vetralia's research consists in discovering, producing and promoting functional works of art capable of arousing a response in the end user both, in emotional and intellectual terms; pieces capable of expressing an innovative vision of the world, but made through processes originating from tradition.
Project conceived, directed
and organized by
© 2023 venicedesignbiennial.org
Fill 29 Created with Sketch. Fill 27 Created with Sketch.

redpajama_set_name: RedPajamaCommonCrawl


text:
(-) Emergency & Safety (28)
(-) Public Affairs & Policy (6)
Policy and Guidance (5)
Technical Reports (32)
Signal and Train Control (119)
(-) Accident Reduction (45)
(-) Motive Power and Equipment (38)
Emergency Declarations (31)
(-) Work Schedule & Sleep Patterns (18)
(-) Risk Reduction Program (16)
Industrial Hygiene (10)
FRA Launches Risk Reduction Safety Program
Subject Accident Reduction
The U.S. Department of Transportation's Federal Railroad Administration (FRA) has issued a final rule, launching the Risk Reduction Program (RRP) to support an increasing...
Effects of In-Pavement Lights on Driver Compliance with Grade Crossing Safety Equipment
Subject Accident Reduction, Grade Crossing Technology, Highway-Rail Grade Crossing Warning Systems, Highway-Rail Grade Crossings
Keywords: Highway-rail, grade crossing, pedestrian behavior, trespass, enhancement, safety, in-pavement lights, violations
This study examined whether in-pavement lights installed at a single grade crossing would increase the number of drivers who obey grade crossing safety signals.
National Strategy to Prevent Trespassing on Railroad Property
Subject Trespasser Programs, Accident Reduction, Grade Crossings
Abstract: Trespassing on railroad property is the leading cause of all rail-related deaths in the United States. More people are struck and killed by trains each year while trespassing –...
Passenger/Freight Train Collision September 12, 2008, Chatsworth, CA : Appendices A.1 Through B.3
Keywords: Transportation, safety, rail accident investigation, crashworthiness, structures and dynamics, Chatsworth collision, passenger train
Passenger/Freight Train Collision September 12, 2008, Chatsworth, CA: Main Report
Keywords: Transportation, safety, rail accident investigation, crashworthiness, structures and dynamics, Chatsworth collision, passenger train, locomotive
Abstract: On September 12, 2008, a passenger train and freight train collided head-on in the Chatsworth district of Los Angeles, CA. Each train was initially travelling at more than 40 mph...


text:
Q: Есть какая-нибудь замена sort в ArrayList? Нужно отсортировать ArrayList, но Android Studio пишет

"Call requires API level 24 (current min is 21): java.util.ArrayList#sort"

есть какая-нибудь замена или можно не сортировку, а просто элементы в случайном порядке по ArrayList раскидать?

A: *

*Collections.sort(list); — сортирует коллекцию, используя компаратор

*Collections.shuffle(list); — перемешивает коллекцию в случайном порядке


My name is Neena I am the manager and have been working in childcare since 2003 and love working with children of all ages and have gained lots of experience with children over the years, from 3 months up to 18 years old. I have got my NVQ level 3 and NVQ level 4 in early years and childcare, I also have my play worker level 2 course and I have worked in various nurseries before running Frizzkids breakfast, after school and holiday club.
My name is Abigail, the children call me Abi. I am the Assistant Manager and have been working for Frizz Kids since 2014 and have gained Level 2 in Playwork. I am currently studying a Leadership skills and Management course. I have learned a lot through various courses attended and constantly gaining knowledge. I love working with children because I like to help them learn and interact with their activities and build friendship.
My name is Latifah and I have been working at Frizz Kids since April 2018. I have already gained great understanding of safeguarding children and am enrolled to do Playworker level 2 course in the new year. I like working with children because they have a positive attitude and they teach me something new every day.


Swiss 721 bt font was designed by Max Miedinger and became first time published on Bitstream in 1982.
This sans serif family that stages in fashion from thin to black while blending in a few unexpected, however beautifully made and sarcastically flattering, define weights that boost the grotesque layout. Swiss 721 takes the essence of mid 20th century sans serif typefaces, and melds it with contemporary layout consistency and a scientific weight variety. You can download this font for free from right here for your personal use only. If you have any kind of question relating about this free font or have any suggestion for us then feel free to comment right down here to share your precious views with us.
0 Response to "Swiss 721 Th BT Font Free Download | Collection Chumbart™"


RSVP today to reserve your spot for our December Monthly Luncheon. Our caterer and speaker will be announced soon. We will have Dahlstrom Middle School Choir joining us to sing Christmas Carols. Reserve your spot today!


text:
Q: Django 'bool' object is not callable При попытке удалить запись из панели администратора получаю ошибку

'bool' object is not callable

models.py
from django.db import models

# Create your models here.

class Series(models.Model):
    name = models.CharField(max_length=200, db_index=True)
    slug = models.SlugField(max_length=200, db_index=True, unique=True)

    class Meta:
        ordering = ['name']
        verbose_name = "Серия"
        verbose_name_plural = "Серии"

    def __str__(self):
        return self.name

class Product(models.Model):
    series = models.ForeignKey(Series, related_name='products', verbose_name="Серия", on_delete=False)
    name = models.CharField(max_length=200, db_index=True, verbose_name="Наименование")
    slug = models.SlugField(max_length=200, db_index=True, unique=True)
    image = models.ImageField(upload_to='products/%Y/%m/%d/', blank=True, verbose_name="Изображение товара")
    description = models.TextField(blank=True, verbose_name="Описание")
    price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Цена")
    stock = models.PositiveIntegerField(verbose_name="В наличии", default=0)
    bought = models.PositiveIntegerField(verbose_name="Количество покупок", default=0)
    available = models.BooleanField(default=True, verbose_name="Доступен")
    created = models.DateTimeField(auto_now_add=True, verbose_name="Добавлен")

    class Meta:
        ordering = ['name']
        verbose_name = "Продукт"
        verbose_name_plural = "Продукты"
        index_together = [['id', 'slug']]

    def __str__(self):
        return self.name

class User(models.Model):
    name = models.CharField(max_length=50, db_index=True, verbose_name="Имя")
    mobile_number = models.CharField(max_length=20)
    telegram_id = models.CharField(max_length=20)
    orders_sum = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Сумма заказов")
    created = models.DateTimeField(auto_now_add=True, verbose_name="Добавлен")

    class Meta:
        ordering = ['name']
        verbose_name = "Пользователь"
        verbose_name_plural = "Пользователи"

    def __str__(self):
        return self.name

class Order(models.Model):
    customer = models.ForeignKey(User, related_name='orders', verbose_name="Заказчик", on_delete=False)
    address = models.CharField(verbose_name='Адрес', max_length=250, null=True)
    payment_type = models.CharField(max_length=50, verbose_name="Тип оплаты", null=True)
    paid = models.BooleanField(default=False, verbose_name='Оплачено')
    send = models.BooleanField(default=False, verbose_name='Отправлено')
    date = models.DateTimeField(auto_now_add=True, verbose_name="Дата", null=True)

    class Meta:
        ordering = ('-date',)
        verbose_name = "Заказ"
        verbose_name_plural = "Заказы"

    def __str__(self):
        return 'Заказ: {}'.format(self.pk)

    def get_total_cost(self):
        return sum(item.get_cost() for item in self.items.all())

class OrderItem(models.Model):
    order = models.ForeignKey(Order, related_name='items', on_delete=False)
    product = models.ForeignKey(Product, related_name='order_items', on_delete=False)
    price = models.DecimalField(verbose_name='Цена', max_digits=10, decimal_places=2)
    amount = models.PositiveIntegerField(verbose_name='Количество', default=1)

    def __str__(self):
        return '{}'.format(self.pk)

    def get_cost(self):
        return self.price * self.amount

admin.py
from django.contrib import admin
from .models import Series, Product, User, Order, OrderItem

class SeriesAdmin(admin.ModelAdmin):
    list_display = ['name', 'slug']
    prepopulated_fields = {'slug': ('name', )}

class ProductAdmin(admin.ModelAdmin):
    list_display = ['name', 'price', 'stock', 'available', 'bought', 'created']
    list_filter = ['available', 'created', 'series']
    list_editable = ['price', 'stock', 'available']
    search_fields = ['name']
    prepopulated_fields = {'slug': ('name',)}

class UserAdmin(admin.ModelAdmin):
    list_display = ['name', 'mobile_number', 'orders_sum', 'created']
    list_filter = ['created']
    search_fields = ['name', 'mobile_number']

class OrderItemInline(admin.TabularInline):
    model = OrderItem
    raw_id_fields = ['product']

class OrderAdmin(admin.ModelAdmin):
    list_display = ['customer', 'paid', 'send', 'date']
    list_editable = ['paid', 'send']
    list_filter = ['paid', 'send', 'date']
    inlines = [OrderItemInline]

admin.site.register(Series, SeriesAdmin)
admin.site.register(Product, ProductAdmin)
admin.site.register(User, UserAdmin)
admin.site.register(Order, OrderAdmin)

Код ошибки

Traceback (most recent call last):
  File "/home/yazon/.local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 35, in inner
    response = get_response(request)
  File "/home/yazon/.local/lib/python3.6/site-packages/django/core/handlers/base.py", line 128, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/home/yazon/.local/lib/python3.6/site-packages/django/core/handlers/base.py", line 126, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/yazon/.local/lib/python3.6/site-packages/django/contrib/admin/options.py", line 575, in wrapper
    return self.admin_site.admin_view(view)(*args, **kwargs)
  File "/home/yazon/.local/lib/python3.6/site-packages/django/utils/decorators.py", line 142, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "/home/yazon/.local/lib/python3.6/site-packages/django/views/decorators/cache.py", line 44, in _wrapped_view_func
    response = view_func(request, *args, **kwargs)
  File "/home/yazon/.local/lib/python3.6/site-packages/django/contrib/admin/sites.py", line 223, in inner
    return view(request, *args, **kwargs)
  File "/home/yazon/.local/lib/python3.6/site-packages/django/utils/decorators.py", line 62, in _wrapper
    return bound_func(*args, **kwargs)
  File "/home/yazon/.local/lib/python3.6/site-packages/django/utils/decorators.py", line 142, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "/home/yazon/.local/lib/python3.6/site-packages/django/utils/decorators.py", line 58, in bound_func
    return func.__get__(self, type(self))(*args2, **kwargs2)
  File "/home/yazon/.local/lib/python3.6/site-packages/django/contrib/admin/options.py", line 1618, in changelist_view
    response = self.response_action(request, queryset=cl.get_queryset(request))
  File "/home/yazon/.local/lib/python3.6/site-packages/django/contrib/admin/options.py", line 1331, in response_action
    response = func(self, request, queryset)
  File "/home/yazon/.local/lib/python3.6/site-packages/django/contrib/admin/actions.py", line 36, in delete_selected
    queryset, opts, request.user, modeladmin.admin_site, using)
  File "/home/yazon/.local/lib/python3.6/site-packages/django/contrib/admin/utils.py", line 131, in get_deleted_objects
    collector.collect(objs)
  File "/home/yazon/.local/lib/python3.6/site-packages/django/contrib/admin/utils.py", line 195, in collect
    return super().collect(objs, source_attr=source_attr, **kwargs)
  File "/home/yazon/.local/lib/python3.6/site-packages/django/db/models/deletion.py", line 222, in collect
    field.remote_field.on_delete(self, field, sub_objs, self.using)
TypeError: 'bool' object is not callable

A: Писать
on_delete=False

неправильно, почитайте в справке что правильно писать в on_delete:

*

*CASCADE удалить вместе с ссылающимися объектами

*PROTECT запретить удаление

*SET_NULL установить в нуль

*SET_DEFAULT ... значение по умолчанию

*SET(значение) ... значение в скобках

*DO_NOTHING удалить оставив битую ссылку


Power and Torque corrected to SAE, EWG (EEC), DIN, etc.
connection of nearly any sensor or instrument possible: e.g. pressures: boost pressure, exhaust back-pressure, oil pressure, temperatures: exhaust gas temperatures, inlet air temperatures, oil and water temp., other temperatures, air / fuel ratio, turbo speed, fuel flow, air flow, etc. - many more possibilities exist.
<-- all data can be printed out in full colour on A4 paper exactly as it is seen on the monitor. The scaling of all axes can be selected freely by the user for optimal settings.
(4) Download: a full sized TAT printout of Ford RS Turbo with boost curve, 2 runs compared (enlarge with VIEW -> ZOOM once visible.
Please e-mail to: Dyno@TAT-RD.com for more information.
we send a reply to every e-mail - if you receive no reply we did not receive your e-mail !


Goodbye letter to a coworker Dear Colleagues I am writing this letter, to you, my co-workers and colleagues to inform you all that in two week s time I will be leaving the organization.
Through this farewell letter, I wish to thank you for your guidance and support. You can leave your phone number and email address so that the coworkers can keep in touch with you.
And now that this dream has become a reality, please know that I could not have reached this goal without your unending lack of support. You want to be remembered as an employee who was courteous, so make sure you mention the good times at the company and how you have grown professionally and personally.
Show your former employer that you take professionalism seriously, under any circumstance. If appropriate, give your reasons for the same.
By writing a good resignation letter! Enjoy… but do not copy and paste for your own farewell email! The short answer is no and that it is better to resign in person and then follow up with an email or hard-copy letter.
Sample Resignation Letter Template. State your intention to resign clearly. They help you acquire new skills, make you feel comfortable in the workplace and help you get used to the work setup. List your name and address, so there is no mistaking who is resigning.
Give Your Contact Details Before ending your goodbye letter for coworkers, remember to furnish your contact details. Being promoted to supervisor brought more challenges, but I could not ask for a better group of billing specialists to supervise.
Ship a goodbye textual content message to want better of luck for the longer term dealings. Do not hesitate to contact me at: How to Write the Letter of Resignation: It is always recommended to depart on good terms and not get in the name calling or accusations when writing your farewell email.
There are certain things that are standard which need to be there along with any additional information that you want to communicate. But some people have an amazing knack to coat a venomous email in slick sugar which eventually brings smiles to all and becomes a classic.
While the main objective of a resignation letter is to inform your employer that you are leaving, you can use it to maintain a positive relationship with the recipient by leaving with a positive final impression. This should be the day you submit your letter. A resignation letter must include: Here, I have found some very good friends and today I am leaving with some wonderful memories of the time we have spent together.
He is leaving to take on bigger challenges elsewhere, but his departure saddens him, as he has built up a great rapport with his co-workers over the years.
If you are leaving for another job, and you feel comfortable disclosing this, go ahead. Use clear language which the recipient can easily understand. Do not boast about the professional growth and monetary gain that you will be achieving with the job change.
Taking that leap may involve writing a resignation letter, so follow the above guidelines, and the process will be smoother than you think. Listed here are few helpful ideas that can assist you write a goodbye letter to colleagues after resignation — Please be at liberty to contact me in future for any assist.Use our free Goodbye Letter to CoWorkers to help you get started.
The Only Resignation Letter Template You'll Ever Need in This is the exact process of writing a resignation letter.
You need to send two, yes, two resignation letters.
(P.S. when I say "letters", I really mean emails. and that is something that the bosses and colleagues you're leaving will be inherently jealous of. Sample Goodbye Emails to Colleagues Since the last post on Saying Goodbye to coworkers, there have been quite a few requests on providing some sample goodbye letters to co-workers and manager.
So here is a compilation of some recommended ones, and one 'on the lighter side' – the 'one' that has traveled around the world through. Home > Careers > Resignation Tips & Templates > Thank you letter to colleagues Thank you letter to colleagues If you would like to write a letter of thanks to your colleagues, use this sample thank you letter as a template.
Farewell Letter To Colleagues. By Letter Writing Leave a Comment. Here is the samples of few goodbye letter to colleagues after resignation with useful letter writing tips. You can also use our goodbye email template for coworkers. One can keep this letter either funny or emotional.
The individual writing this letter is resigning to transfer to a different company as a manager. This appreciation letter to colleagues after a resignation letter sample is for the group of billers the person supervises.


text:
Gov. Cooper to appeal court ruling allowing N.C. bowling alleys to reopen
Ruling allows bowling alleys to reopen, gov. says he'll appeal
By GARY D. ROBERTSON | AP | July 7, 2020 at 4:04 PM EDT - Updated July 7 at 5:37 PM
RALEIGH, N.C. (WBTV/AP) - North Carolina Governor Roy Cooper says he will appeal Tuesday's court ruling allowing bowling alleys to reopen across the state.
"Hospitalizations and positive cases are reaching record highs while the Governor works to get schools open and prevent the state from going backward on restrictions," a statement from Cooper's office reads. "The Governor will immediately appeal this ruling that harms both of these efforts."
House Speaker Tim Moore also commented on the court's ruling, and Cooper's handling of the closures.
"This court decision reflects the difficult reality that the Governor has chosen winners and losers in North Carolina's economy without any justification or consistency, devastating some family businesses while helping others," Speaker Moore said. "The Governor's inconsistent approach to closing businesses has been unfair, inequitable, and thus illegal from the start. I continue to urge the Governor to produce a plan for all North Carolina companies, to communicate that plan, and to help businesses comply with consistent protocols so they may safely operate."
In June, N.C. legislators sent a bill to Cooper designed to overturn parts of his executive order for COVID-19 that's kept several types of retail businesses shuttered for months.
The General Assembly finalized a measure to let bowling alleys and ice and roller rinks to reopen at a reduced capacity.
In June, Cooper vetoed one measure that sought to reopen gyms as well as bars by letting them serve patrons outdoors.
[ Gov. Roy Cooper vetoes updated bill that would have reopened N.C. gyms, bars ]
There is no word on when Cooper will veto the court's latest decision.


Coasters, hair clips and more emoji crafts to make at home with your kids this week.
Emojis aren't new to our everyday conversations, but there are more options than ever! From your classic smile to devilish grins, emojis help us add some silliness into our days. They can even try and sum up what we're saying with just one icon, too. Brands like Chevy have used emojis for advertising campaigns and even the MTV Video Music Awards have put the images to work. No matter how you use them, chances are you've already used one today. For the emoji lovers in your house, this week's roundup is dedicated to all-things emoji.
No need to translate this post from The Craft Swedes – it's very easy to understand! A basic Perler Bead form and colorful beads are what you'll need to make these emoji coasters.
Give your hair the emoji treatment with this project from eHow. Small pieces of felt are added to simple barrettes to create these charming accessories.
Put those emojis to work organizing your child's craft supplies! Our Messy Table upcycles empty mason jars into cheery desk accessories.
These DIY pinatas from I Spy DIY are so cute you may not want to break them. But if there's good candy inside, no emoji pinata is safe!


"Secret Agent Manafort." President of Planned Parenthood Calls Out Lies About Abortion and Health Care. Whatever You Do DON'T Follow @DevinCow. #MeToon. Means TV: For All of Us.
Press Secretary Sarah Huckabee Sanders tweeted a doctored video clip from Infowars in which they sped up Jim Acosta's hand movement in an effort to discredit a reputable journalist. She should be forced to resign for this.


We have a partnership with just about the most famous UK datacenters – Pulsant, which's situated a couple of miles north west of London. This particular facility offers a top level of security and is also staffed by knowledgeable admins who take care of the server network 24x7x365.
If your sites are aimed toward clients within the UK, the rest of Europe as well as Africa, then the Pulsant datacenter is an ideal selection for you. That way, your sites are going to be actually nearer to your visitors, which usually does provide swifter website loading rates.
In our data center in UK, our company offers shared web hosting and semi-dedicated servers. Consequently, you're able to host any kind of website – starting with your personal blog or portfolio webpage, to a prosperous online store, a community website or even a information web site.
All the UK located shared web hosting offers include the unique Site Control Panel. It is created to live in the cloud and it also makes it simple to control all your domain names and web sites from a single place. You receive use of a great deal of cost–free software tools, which will help you better take care of your website – a drag–and–drop File Manager, multifunctional Domain Manager and mail account manager, a group of Site Accelerator Instruments like Memcached and Varnish, as well as an extensive web statistics tool.
What's more all UK located shared web hosting packages are completely risk–free! They have a 99.9% service uptime warranty plus a 30–day money–back guarantee. In case you are not contented with our products for whatever reason – you can have a reimbursement, no questions asked.
The UK Located VPS Servers are a superb choice if you prefer a brand new home for your personal well–known website or you demand a development location for your forthcoming multi-media project. Papa Hosting's UK virtual private servers are equipped with SSD hard drives that have very fast file read/write rates. Furthermore, every UK Located VPS Server includes a 99.9% network uptime guarantee. You also select the Operating System that will power your server as well as your control panel.
All of our semi-dedicated servers represent a unique hosting solution, which combines the processing power of a dedicated server with the user-friendliness of a common hosting account. Having a semi-dedicated server in our UK data center, you'll be able to attract more clients from Europe because of the fantastic connectivity options that we offer.
Each semi-dedicated server is backed up by 99.9% server and network uptime warranties. In addition, you will get a lot of free of cost bonuses with your server - a complimentary dedicated IP, a collection of website accelerators and more.
All the shared web hosting plans in the data center in UK have a 99.9% service uptime together with a 99.9% network uptime guarantee!
Reasonably–priced UK located shared web hosting solutions. Make a comparison of our UK located shared web hosting packs to discover the best one for your requirements.
Choose Papa Hosting and enjoy finest connection rates for your websites from any area on the planet thanks to Papa Hosting's state-of-the-art datacenters.
Papa Hosting's Sales personnel are ready to assist you any moment. Give us a call whenever you want.


Offering a 0% APR deal attracts customers and allows you to stand out from the crowd. No deposit required on this package makes it a great deal for your customer.
THE BOILER SELLER!. An unbeatable package on the Boiler Finance Market. This is by far our most popular package. Take the stress away from your customer and offer the whopping 6 months No Deposit No Payments package.
Don't let your customer go off the boiler!. Finance approved in less than 5 minutes. Electronic documents mean you can fit the boiler immediately or at a time convenient to your customer.
No upfront costs for the boiler pack. Collect the boiler from your local merchants at no cost to you or arrange the purchase of the boiler pack yourself. Install the boiler as normal.
Great cash flow and quick payment terms. We will pay you your quoted amount in full the week after the boiler installation is complete.


text:
El término Les Cabannes o Cabannes puede referirse a:

 Cabannes, comuna francesa de Bocas del Ródano.
 Les Cabannes, comuna francesa de Ariège.
 Les Cabannes, cantón de Francia.
 Les Cabannes, comuna francesa del departamento del Tarn.
 Jean Cabannes (1885-1959) físico francés.
 Cráter lunar «Cabannes».
 Laurent Cabannes (1964-) jugador de rugby.
 Romain Cabannes (1984-) jugador de rugby.

redpajama_set_name: RedPajamaWikipedia


Enniskillen Royal Grammar School pupil Sophia Williams made her debut for the Irish Cross Country team running at an International Schools' event at Santry, Dublin at the weekend.
Sophia (14) was selected as one of four Ulster athletes to make up the Irish squad running against the top athletes from English, Welsh and Scottish schools.
While the event was dominated by the English schools who seemed to favour the 3km flat fast course, Sophia had an excellent race crossing the line in an impressive time of 11.23 and a top 30 placing.
Many household names have started their athletics career at the International Schools Cross Country event and Sophia is hoping that this is only the start of an international athletics career.


text:
Prince Harry may open up about 'racially insensitive' past mistakes: royal author
A royal biographer has suggested Prince Harry may address some of the 'racially insensitive' mistakes that have seen him come under scrutiny over the years.
The Duke of Sussex has become increasingly vocal on the issue of racism in recent weeks, even suggesting the Commonwealth should reckon with its colonial history.
RELATED: Harry speaks about 'institutional racism' in speech for The Diana Award
Prince Harry is "still educating himself", says royal author Omid Scobie. (Getty images)
However, some commentators have suggested the royal needs to address the mistakes from his own past, including wearing a Nazi costume to a party and referring to an army friend using a racial slur.
According to Omid Scobie, co-author of the new Duke and Duchess of Sussex biography Finding Freedom, Harry may be preparing to take this step.
"He's on a journey at the moment, and I do think that at some point we'll hear him really talk about that journey and what he's learnt on that," he told ITV's True Royalty TV, per The Mirror.
LISTEN: 9Honey's royal podcast The Windsors looks back on Harry's days as the 'party prince', and the controversies that resulted. (Post continues.)
"But I think at the moment ... he's still educating himself. Maybe he feels he's not there yet."
In 2005, photos of Harry wearing a Nazi uniform, including a swastika armband, to a friend's dress-up party landed on the front page of UK newspaper The Sun.
The prince, then 20, apologised in a statement, acknowledging the outfit was "a poor choice of costume".
"I am very sorry if I caused any offence or embarrassment to anyone," he said.
Harry and wife Meghan Markle have been vocal on issues of racism this year. (AP)
Harry was in hot water again in 2009 when footage emerged of him referring to a fellow army cadet with a racist phrase while training at Sandhurst military academy.
The video was recorded three years earlier, when the royal was 21.
St James' Palace responded to public criticism of the prince's choice of words, saying he was "extremely sorry" for any offence caused.
"Prince Harry fully understands how offensive this term can be," the statement added.
WATCH: How the pandemic has impacted Harry and Meghan's post-royal split plans. (Post continues.)
"However, on this occasion three years ago, Prince Harry used the term without any malice and as a nickname about a highly popular member of his platoon.
"There is no question that Prince Harry was in any way seeking to insult his friend."
RELATED: How Meghan has used her platform to condemn racism
The Duke of Sussex and his wife Meghan have both spoken out about systemic racism since resigning from their royals as senior working royal family members in March.
In a rare TV appearance on Good Morning America, Harry stressed it was not "down to the Black community" to weed out the problem.
Harry pictured his recent Good Morning America interview. (YouTube)
"This is down to every single person that is on the planet right now," he said.
"Why wouldn't you want to be part of the solution? If you can't answer that honestly, then I think you're part of the problem rather than part of the solution."
The Duke and Duchess of Sussex have stated they had no involvement in Finding Freedom, written by Scobie and fellow royal reporter Carolyn Durand.
How Harry and Meghan's love story began
Property News: When it comes to a partner's annoying home habits, should we live and let live? - domain.com.au


SINGAPORE- Police have arrested a 27-year-old man believed to be involved in a case of housebreaking at Toh Guan Road East Industrial Estate.
Around 7.50am on Tuesday morning, the Police were alerted to a break-in at a unit there. Three drills, a cash register, and cash amounting to about $4,000 were reported stolen.
Officers from the Clementi Police Division began investigating.
The suspect was arrested along Geylang Lorong 8 on the same day at about 1.30pm.
The officers also recovered three drills and $2,337 in cash, believed to have been stolen by the man.
He will be charged in court on Jan 14 with Housebreaking and Theft by Night, which carries an imprisonment term of up to 14 years.


text:
Pakistan looks to new tech to curb crop burning and cut smog
by Rina Saeed Khan | @rinasaeed | Thomson Reuters Foundation
Tuesday, 8 December 2020 06:00 GMT
A demonstration of subisidized farm equipment for Pakistani rice farmers in Sheikhupura, Punjab, Pakistan, November 8, 2020. Photo: Ansab Ali, Ministry of Climate Change
About our Climate coverage
We focus on the human and development impacts of climate change
Subsidised farm machinery that eliminates the need to burn fields could improve Lahore's choking air pollution, government hopes
By Rina Saeed Khan
LAHORE, Pakistan, Dec 8 (Thomson Reuters Foundation) - Air pollution is a long-standing problem in Pakistan, but every October and November contaminates in the air in Punjab province shoot up as farmers burn rice stalks left behind after harvesting to clear their fields to plant wheat.
During these cooler months, the provincial capital Lahore, which is surrounded by rice-growing districts, is covered with thick smog.
"It is a health emergency – the air quality monitors in Lahore routinely show hazardous levels in November," said Farah Rashid, a climate and energy programme coordinator for green group WWF-Pakistan.
Now the Punjab government hopes to tackle the problem by providing 500 rice farmers around Lahore with a set of machines that together eliminate the need to burn crop stubble.
The machines include a shredder that breaks down rice stubble and mulches it into the ground and a seed drill - called the Happy Seeder - that follows to sow wheat through the mulch.
"It's a useful technology," said farmer Aaamer Hayat Bhandara, who has used both machines at a friend's large farm, and has pushed the government to subsidise them.
"These machines used together could really make life much easier for us farmers," said Bhandara, from Pakpattan in Punjab province.
Malik Amin Aslam, climate change advisor to Prime Minister Imran Khan, called air pollution a "silent killer" and said Lahore's smog had increased in intensity and frequency over the last five years.
He explained that rice farmers traditionally use combine harvesters to cut their rice in October, leaving behind about four inches of stubble.
With less than two weeks before they have to ready their fields to sow wheat, burning is the fastest way to clear the land, he told the Thomson Reuters Foundation.
In Pakistan, rice is grown on an area of about 2 million hectares (5 million acres), mainly in the Punjab and Sindh provinces. Many of the fields are cleared by burning every year.
In October and November, Lahore's Air Quality Index level can jump to over 300, a number that the U.S. Environmental Protection Agency says corresponds to a "health warning of emergency conditions".
Malik Amin Aslam, climate change advisor to Prime Minister Imran Khan, speaks with a farmer at the launch of a programme to subisidize farm equipment for Pakistani rice farmers in Sheikhupura, Punjab, Pakistan, November 8, 2020. Photo: Ansab Ali, Ministry of Climate Change
Farmers say the new farm equipment can help combat smog, but note that crop burning produces only a small share of the province's pollution.
"The stubble is burned only for a few weeks in the winter. It is a fact that the problem becomes worse during this short period," Bhandara said.
"But farmers are not the only reason for this pollution," he added.
A 2018 report by the U.N. Food and Agriculture Organization (FAO) on the underlying causes of smog in Punjab noted that agriculture - mainly rice residue burning - accounts for 20% of total air pollutant emissions.
That puts it behind industry, which produces a quarter of the air pollution in the province, and transport, which contributes more than 40%.
Tackling air pollution - and leaving stubble on the soil as mulch, rather than burning it - also has the benefit of reducing carbon emissions that contribute to climate change.
In India, where farmers have been using the rice stubble shredder and Happy Seeder for the past few years, a group of scientists published a report last year stating the technology could cut greenhouse gas emissions by as much as 78%.
Ejaz Ahmad, an environmental expert with the Institute of Urbanism in Islamabad, said any efforts to curb air pollution will benefit Pakistanis.
"The Happy Seeder seems like a useful machine," he said.
CHOSEN BY LOTTERY
In Mandi Bahauddin district, where famed Basmati rice is grown, Muhammad Afzal, an agriculture officer at Punjab's Government Agriculture Seed Farm, has been experimenting with the Happy Seeder for the past two years.
"Stubble management is a serious issue for farmers," said Afzal, who helps farmers adopt new farming techniques.
Pakistan has penalties for rice stubble burning, including fines of up to 20,000 Pakistani rupees ($125) per acre - but most farmers have little other choice and simply continue the practice and pay the penalty when they are charged.
But a growing number are looking for alternative solutions, Afzal said.
The total cost for the stubble shredder and Happy Seeder is about 637,500 rupees ($4,000), and the government this year is paying about 80% of the price for 500 farmers, he noted.
"For those who can't afford it, bigger farmers are willing to rent out the machines. In the future, more service providers will come up to rent them out," Afzal said.
One drawback to the machines, he noted, is the need to mount them on the back of a tractor - and not just any tractor will do.
"It requires a large, 85-horsepower tractor," he noted, something most rice farmers in Pakistan do not have.
Bhandara, the farmer in Pakpattan, said the subsidised machines also are only available in certain districts around Lahore, in the so-called smog "red zone".
"The subsidised machines should be made available to rice farmers in South Punjab and Sindh as well, otherwise they are too expensive for most farmers," he said.
Despite the limitations, the Happy Seeder has proven so popular that the government has had 10 applicants for each of its 500 machines, according to Aslam, the climate change advisor.
He said authorities are using a lottery system to decide who gets the subsidised equipment.
The government has plans to expand the Happy Seeder programme next year and cover the whole of the Punjab rice belt by 2023, Aslam noted.
In the meantime, he added, it is already working on a technology upgrade.
"The agriculture extension department has developed a prototype to combine the two shredder (and) seeder machines into one 'Pak Seeder', which will be even more effective and efficient" - plus 30% cheaper, he said.
As Lahore chokes on winter smog, Pakistan moves to cut air pollution
Pakistan launches electric vehicle plan with cars in slow lane
Polluted air to shorten lives by 20 months, researchers say
(Reporting by Rina Saeed Khan; Editing by Jumana Farouky and Laurie Goering. Please credit the Thomson Reuters Foundation, the charitable arm of Thomson Reuters, that covers the lives of people around the world who struggle to live freely or fairly. Visit http://news.trust.org/climate)
Climate Change General
Adapting to Climate Change
EXPLORE MORE Climate NEWS
Biden to revoke KXL pipeline permit in blow to Canada's oil sector
Toxic air seen cutting thousands of lives short each year in Europe's cities
Scientists warn climate change is harming children's diets
Campaigners to Biden: Environmental justice key to tackling climate change


Guide: Which kind of child insurance is better to buy? In this regard, the insurance home _ Wobao experts said that children's insurance is rich in variety, must be tailored to the characteristics of the child's activities. While choosing "


text:
datagridview rowvalidating event example
Adult chat rooms no java
Who is lisa kudrow dating
As a teenager, Kudrow excelled at tennis and played on the varsity team at Taft High School in Los Angeles.
After earning a degree in biology from Vassar College in Poughkeepsie, New York, Kudrow returned to Los Angeles to work with her father and follow a career in research.
Later, after numerous friendly interactions, Lisa and Michel found out that they had a lot in common.
He started enjoying Lisa's company after her shy and polite nature impressed him.
Leveraging the fame from her top-rated TV show, Kudrow transitioned to the big screen in movies such as featured Kudrow as Valerie Cherish, a washed-up sitcom actress attempting to make her return to the business.
The show aired for 13 episodes and was cancelled, only to be revived in 2014 for a second season.
Apart from her career break-through show, Friends, Lisa has also appeared in the mega-hit series Scandal and Web Therapy.
Kudrow has also served as an executive producer of a genealogy-themed documentary series in which celebrities trace their family roots.
In a 2010 episode, Kudrow explored her own family tree of ancestors who immigrated from Belarus, Germany and Hungary.
Michel met his wife Lisa back in late 1980's when he dropped by her apartment to pick up her roommate.
He was dating her French roommate for few weeks at that time.
Previous Post interracialdatingservice com
Next Post Free explicit sex cams
Grannies webcam online 03-Jan-2020 03:15
Please contact Page Keller ([email protected]) if you have any questions. To download the full Call for Proposals, click below: for Proposals: Submissions Due April 2 CRLA is accepting proposals for 60 and 90-minute concurrent sessions, 60-minute round tables, and half and full-day pre-conference institutes for our 2018 Annual Conference.
santa killer dating 19-Nov-2019 13:45
Mairead, who is 38, blonde and delightfully blunt, asks me to fill her in on my background, and tell her what I look for in a man.
latin dating usa 02-Sep-2019 09:49
But those who aren't the type for finding sex in an app may not view Pure in the purest light, so keeping profiles out of the public eye and the line of ridicule is probably best for everyone. But for those of you who live in smaller towns, don't want to have sex with strangers, or are particular about your partner, you'll likely want to scout your options for more than an hour. All you'll get from it is a hard deadline, a few pictures, and a short corny tagline.
gay dating bible 07-Oct-2019 21:32
According to Jon Husby, director of automotive for Tele Atlas, one of the leading map data providers, 2006 marked the year sales of portable navigation systems surpassed those of in-car systems for the first time.
Sex phone chat of atlanta 06-Oct-2019 16:27
Petersburg (1) Festive Recipes (2) FIBA (1) FIFA (15) FIFA 2018 (5) FIFA Fan Fest (2) FIFA Fan Festival (2) FIFA Russia (4) FIFA Russia 2018 (11) FIFA Russia Cities (7) FIFA World Cup (28) FIFA World Cup 2014 (4) FIFA World Cup 2018 (2) FIFA world cup 2018 tickets (30) fighting drugs (2) Figure Skating (7) Filigree (1) Filipp Malyavin (2) Filling Stations (1) Film "Mathilda" (1) Film Archives (1) Film award (1) film awards (1) Film Directors (2) Film Distribution (22) Film Distribution in Russia (1) Film Festival (11) Film Festival "Eurasian Bridge" (1) Film Festival "Message to Man" (1) Film Festival "Movement" (1) Film Festivals (106) Film Festivals in Russia (1) Film Prizes (1) Film Restoration (1) Film service (1) films (1) Films Festivals (5) Filyovsky Park (1) Finam Aerodrome (1) Finance (1) Finance Minister (1) Finance Ministry (5) financial markets (1) Finds (10) Fine Art (1) Fine Arts (9) Fine Arts Festival "Traditions and the Present" (1) Fines (1) Finland (4) Fire (9) fire accident (3) firefighting (2) Fires (12) Fireworks (1) Fish Broth (1) Fishers Day (1) Fishing (2) Fist Fights (1) Fitch (1) fitness in Moscow (2) Flacon Design Factory (4) Flaertiana (1) Flahertiana (1) Flakon design factory (1) Flamenco (1) Flashmob (1) flat rent in Moscow (1) flavor enhancer (1) Flea Market (2) Flea Markets (1) Flemings (1) Flemish Painters (1) flight (1) Flight Accident (2) flight discounts (1) Flights to Moscow (1) flights to Russia (2) Flights to the Mars (2) Flights to the Moon (4) Floating Hotels (2) Floating University (3) flood (3) flood in Amur region (2) Flood in Khabarovsk (2) Flood in the Far East (1) flooding in Moscow (1) Floods (1) floods in Far East (2) floods in Moscow (1) Flor Garduno (1) Flower Festivals (2) Flowers (1) Flowers Ban (1) fluorescent proteins (1) Flutes (1) Flying Laboratory (1) Flying Saucer (1) Flying without fear (1) flyover (1) Foam Rubber Bobsleigh (1) Fokino (1) Folk Art (9) Folk Art Festivals (1) Folk Arts (13) Folk Arts and Crafts (8) Folk Chorus (1) Folk Crafts (1) Folk Graphic Art Museum (1) Folk Music (2) Folk Music Festival "Red Sun" (1) Folk Music Instruments (1) Folk Songs (1) Folk Theatre (2) Folk Toys (8) food products (1) Food Show Christmas (1) foods import ban (3) Football (15) Football championship 2018 (1) football in Russia (1) Football Stadium Kazan Arena (1) Forbes (1) foreign agent (2) Foreign Currency (1) foreign investment in Russia (1) foreign language films (1) foreign literature (1) Foreign Minister Sergey Lavrov (1) foreign passport (2) Foreign Policy (6) foreign tourism in Russia (1) foreign workers (3) Forest Fire (1) Forest Fires (5) Forest Museum (1) Forest of Victory (1) Forest Reserves (1) Forestry (1) Forex (1) former USSR, (1) Formula 1 (2) Formula E (1) Fortresses (1) Fortresses of Russia (1) forum (1) foul language in Russia (1) fountain (1) Fountain Season (2) fountains in Moscow (1) Fountains of St. Copyright to the content of the Site including, but not limited to, text, photos, graphic designs, is owned by Garant-Info Centre.
Voice chat sexsites 30-Aug-2019 16:57
The two were the first to have an end gay outline on behalf television and 12 no later, they are still bias boss.
One of the major perks of having a sexy chat on webcam is that everything is interactive.
long distant dating
insert auto updating date in word
Free uk senior sex chat
garden grove catholic dating
Albanian dating site sex
guidelines for dating
© 2017 sdalsnyal.ru


Technically it doesn't get much better; Galina shows pure talent and inhuman body control and strength.
Make sure to watch this absolutely stunning pole dancing performance by Rebecca Star at the Florida Pole Fitness Championship!
Pole dancing video of Edouard Doye who is the 2010 French Pole Dance Competition Winner and 2011 International Pole Art Competition Winner.


text:
Get ready, the weekend brings extreme cold!
environment Hungary Lake Balaton nature useful weather weather forecast
Photo: MTI/Komka Péter
A lot of sunshine is expected on the weekend, and snow can only be expected in some places. The National Meteorological Service says that we need to prepare for cold temperatures and freezing during the day; in some cases, we might even measure minus 20 degrees in the morning.
Several hours of sunshine are expected in most of the country on Saturday. There may be more cloudy periods, mainly in the north-eastern and eastern landscapes and in Western Transdanubia. There may be snow showers here and there, but they are more likely in the northeast.
The lowest temperatures are likely to be between minus 14 and minus 8 degrees, but in clear, wind-protected, snowy areas, they can measure up to minus 20 degrees.
Freezing weather causes growing chaos in Hungary! – Photos, videos
Freezing! This week brings extreme cold to Hungary
According to Index, the maximum temperature will vary between minus 7 and minus 1 degree.
There might be occasional snow showers on Sunday. During the day, the sun will shine for several hours, while in the eastern part of the country, there may be more cloudy areas.
Photo: MTI/Varga György
The northern and north-west winds can be expected to strengthen. During the coldest hours, the temperature will usually be between minus 12 and minus 5 degrees, but in clear, wind-protected, snowy parts, it can even reach 16 degrees.
Daytime maximum temperatures are expected to vary between minus 5 and plus 3 degrees.
Source: www.index.hu
Medicine shortage can stay for a long time in Hungary
Hungarian tourism boomed in 2022, but where did most of the visitors come from?
President Novák meets Azeri counterpart Ilham Alijev in Budapest
Stadiums, World Championships: multiple priced prestige projects in Hungary


text:
package aliyunecs

import (
	"crypto/md5"
	"crypto/rand"
	"fmt"
	mrand "math/rand"

	"github.com/denverdino/aliyungo/common"
	"github.com/denverdino/aliyungo/ecs"
	"github.com/denverdino/aliyungo/slb"

	"io"
	"io/ioutil"
	"net"
	"net/url"
	"strconv"
	"strings"
	"time"

	"github.com/docker/machine/libmachine/drivers"
	"github.com/docker/machine/libmachine/log"
	"github.com/docker/machine/libmachine/mcnflag"
	"github.com/docker/machine/libmachine/mcnutils"
	"github.com/docker/machine/libmachine/ssh"
	"github.com/docker/machine/libmachine/state"
	//"os"
)

const (
	driverName               = "aliyunecs"
	defaultRegion            = "cn-hangzhou"
	defaultInstanceType      = "ecs.n4.small"
	defaultRootSize          = 20
	internetChargeType       = string(common.PayByTraffic)
	ipRange                  = "0.0.0.0/0"
	machineSecurityGroupName = "docker-machine"
	vpcCidrBlock             = "10.0.0.0/8"
	vSwitchCidrBlock         = "10.1.0.0/24"
	timeout                  = 300
	defaultSSHUser           = "root"
	maxRetry                 = 20
)

var (
	dockerPort = 2376
	swarmPort  = 3376
)

type Driver struct {
	*drivers.BaseDriver
	Id                      string
	AccessKey               string
	SecretKey               string
	Region                  common.Region
	ImageID                 string
	SSHPassword             string
	SSHKeyPairName          string
	SSHPrivateKeyPath       string
	PublicKey               []byte
	InstanceId              string
	InstanceType            string
	PrivateIPAddress        string
	SecurityGroupId         string
	SecurityGroupName       string
	ReservationId           string
	VpcId                   string
	VSwitchId               string
	Zone                    string
	PrivateIPOnly           bool
	InternetMaxBandwidthOut int
	InternetChargeType      common.InternetChargeType
	RouteCIDR               string
	SLBID                   string
	SLBIPAddress            string
	Tags                    map[string]string
	DiskSize                int
	DiskFS                  string
	DiskCategory            ecs.DiskCategory
	Description             string
	IoOptimized             bool
	APIEndpoint             string
	SystemDiskCategory      ecs.DiskCategory
	SystemDiskSize          int
	ResourceGroupId string

	client    *ecs.Client
	slbClient *slb.Client
}

func (d *Driver) GetCreateFlags() []mcnflag.Flag {
	return []mcnflag.Flag{
		mcnflag.StringFlag{
			Name:   "aliyunecs-access-key-id",
			Usage:  "ECS Access Key ID",
			Value:  "",
			EnvVar: "ECS_ACCESS_KEY_ID",
		},
		mcnflag.StringFlag{
			Name:   "aliyunecs-access-key-secret",
			Usage:  "ECS Access Key Secret",
			Value:  "",
			EnvVar: "ECS_ACCESS_KEY_SECRET",
		},
		mcnflag.StringFlag{
			Name:   "aliyunecs-image-id",
			Usage:  "ECS machine image",
			EnvVar: "ECS_IMAGE_ID",
		},
		mcnflag.StringFlag{
			Name:   "aliyunecs-region",
			Usage:  "ECS region, default cn-hangzhou",
			Value:  defaultRegion,
			EnvVar: "ECS_REGION",
		},
		mcnflag.StringFlag{
			Name:   "aliyunecs-vpc-id",
			Usage:  "ECS VPC id",
			Value:  "",
			EnvVar: "ECS_VPC_ID",
		},
		mcnflag.StringFlag{
			Name:   "aliyunecs-vswitch-id",
			Usage:  "ECS VSwitch id",
			Value:  "",
			EnvVar: "ECS_VSWITCH_ID",
		},
		mcnflag.StringFlag{
			Name:   "aliyunecs-zone",
			Usage:  "ECS zone for instance",
			Value:  "",
			EnvVar: "ECS_ZONE",
		},
		mcnflag.StringFlag{
			Name:   "aliyunecs-security-group",
			Usage:  "ECS VPC security group",
			Value:  "docker-machine",
			EnvVar: "ECS_SECURITY_GROUP",
		},
		mcnflag.StringFlag{
			Name:   "aliyunecs-instance-type",
			Usage:  "ECS instance type",
			Value:  defaultInstanceType,
			EnvVar: "ECS_INSTANCE_TYPE",
		},
		mcnflag.StringFlag{
			Name:   "aliyunecs-private-ip",
			Usage:  "ECS VPC instance private IP",
			Value:  "",
			EnvVar: "ECS_VPC_PRIVATE_IP",
		},
		mcnflag.StringFlag{
			Name:   "aliyunecs-description",
			Usage:  "Description for instance",
			Value:  "",
			EnvVar: "ECS_DESCRIPTION",
		},
		mcnflag.StringFlag{
			Name:   "aliyunecs-ssh-password",
			Usage:  "Set the password of the ssh user",
			EnvVar: "ECS_SSH_PASSWORD",
		},
		mcnflag.StringFlag{
			Name:   "aliyunecs-ssh-keypair",
			Usage:  "Set the SSH key pair name",
			EnvVar: "ECS_SSH_KEYPAIR",
		},
		mcnflag.StringFlag{
			Name:   "aliyunecs-ssh-keypath",
			Usage:  "File path of SSH private key",
			EnvVar: "ECS_SSH_KEYPATH",
		},
		mcnflag.BoolFlag{
			Name:   "aliyunecs-private-address-only",
			EnvVar: "ECS_PRIVATE_ADDR_ONLY",
			Usage:  "Only use a private IP address",
		},
		mcnflag.IntFlag{
			Name:   "aliyunecs-internet-max-bandwidth",
			Usage:  "Maximum bandwidth for Internet access (in Mbps), default 1",
			Value:  1,
			EnvVar: "ECS_INTERNET_MAX_BANDWIDTH",
		},
		mcnflag.StringFlag{
			Name:   "aliyunecs-internet-charge-type",
			Usage:  "Internet charge type, the valid values are PayByTraffic (default) or PayByBandwidth",
			Value:  internetChargeType,
			EnvVar: "ECS_INTERNET_CHARGE_TYPE",
		},
		mcnflag.StringFlag{
			Name:   "aliyunecs-route-cidr",
			Usage:  "Docker bridge CIDR for route entry in VPC",
			EnvVar: "ECS_ROUTE_CIDR",
		},
		mcnflag.StringFlag{
			Name:   "aliyunecs-slb-id",
			Usage:  "SLB id for instance association",
			EnvVar: "ECS_SLB_ID",
		},
		mcnflag.StringSliceFlag{
			Name:   "aliyunecs-tag",
			Usage:  "Tags for instance",
			Value:  []string{},
			EnvVar: "ECS_TAGS",
		},
		mcnflag.IntFlag{
			Name:   "aliyunecs-disk-size",
			Usage:  "Data disk size for instance in GB",
			Value:  0,
			EnvVar: "ECS_DISK_SIZE",
		},
		mcnflag.StringFlag{
			Name:   "aliyunecs-disk-fs",
			Usage:  "File system for data disk (ext4 or xfs)",
			Value:  "ext4",
			EnvVar: "ECS_DISK_FS",
		},
		mcnflag.IntFlag{
			Name:   "aliyunecs-system-disk-size",
			Usage:  "System disk size for instance in GB",
			Value:  40,
			EnvVar: "ECS_SYSTEM_DISK_SIZE",
		},
		mcnflag.StringFlag{
			Name:   "aliyunecs-system-disk-category",
			Usage:  "System disk category for instance",
			EnvVar: "ECS_SYSTEM_DISK_CATEGORY",
		},
		mcnflag.StringFlag{
			Name:   "aliyunecs-disk-category",
			Usage:  "Data disk category for instance",
			EnvVar: "ECS_DISK_CATEGORY",
		},
		mcnflag.BoolFlag{
			Name:   "aliyunecs-upgrade-kernel",
			Usage:  "Upgrade kernel for Ubuntu 14.04 instance (deprecated)",
			EnvVar: "ECS_UPGRADE_KERNEL",
		},
		mcnflag.StringFlag{
			Name:   "aliyunecs-io-optimized",
			Usage:  "I/O optimized instance",
			Value:  "true",
			EnvVar: "ECS_IO_OPTIMIZED",
		},
		mcnflag.StringFlag{
			Name:   "aliyunecs-api-endpoint",
			Usage:  "Custom API endpoint",
			Value:  "",
			EnvVar: "ECS_API_ENDPOINT",
		},
		mcnflag.StringFlag{
			Name:   "aliyunecs-resource-group-id",
			Usage:  "ResourceGroupId for instance",
			Value:  "",
			EnvVar: "ECS_RESOURCE_GROUP_ID",
		},

	}
}

func NewDriver(hostName, storePath string) drivers.Driver {
	id := generateId()
	return &Driver{
		Id: id,
		BaseDriver: &drivers.BaseDriver{
			SSHUser:     defaultSSHUser,
			MachineName: hostName,
			StorePath:   storePath,
		}}
}

func (d *Driver) GetImageID(image string) string {

	if len(image) != 0 {
		return image
	}
	args := ecs.DescribeImagesArgs{
		RegionId:        d.Region,
		ImageOwnerAlias: ecs.ImageOwnerSystem,
	}

	// Scan registed images with prefix of default Ubuntu image
	for {
		images, pagination, err := d.getClient().DescribeImages(&args)
		if err != nil {
			log.Errorf("%s | Failed to describe images: %v", d.MachineName, err)
			break
		} else {
			for _, image := range images {
				if strings.HasPrefix(image.ImageId, defaultUbuntuImagePrefix) {
					return image.ImageId
				}
			}
			nextPage := pagination.NextPage()
			if nextPage == nil {
				break
			}
			args.Pagination = *nextPage
		}
	}

	//Use default image

	image = defaultUbuntuImageID

	return image
}

func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error {
	d.APIEndpoint = flags.String("aliyunecs-api-endpoint")
	var region common.Region
	var err error
	regionId := flags.String("aliyunecs-region")
	if d.APIEndpoint != "" {
		// Ignore the Region validation
		region = common.Region(regionId)
	} else {
		region, err = validateECSRegion(flags.String("aliyunecs-region"))
		if err != nil {
			return err
		}
	}
	d.AccessKey = flags.String("aliyunecs-access-key-id")
	d.SecretKey = flags.String("aliyunecs-access-key-secret")
	d.Region = region
	d.ImageID = flags.String("aliyunecs-image-id")
	d.InstanceType = flags.String("aliyunecs-instance-type")
	d.VpcId = flags.String("aliyunecs-vpc-id")
	d.VSwitchId = flags.String("aliyunecs-vswitch-id")
	d.SecurityGroupName = flags.String("aliyunecs-security-group")
	d.Zone = flags.String("aliyunecs-zone")
	d.SwarmMaster = flags.Bool("swarm-master")
	d.SwarmHost = flags.String("swarm-host")
	d.SwarmDiscovery = flags.String("swarm-discovery")
	d.SSHUser = defaultSSHUser
	d.SSHPassword = flags.String("aliyunecs-ssh-password")
	d.SSHKeyPairName = flags.String("aliyunecs-ssh-keypair")
	d.SSHPrivateKeyPath = flags.String("aliyunecs-ssh-keypath")
	d.SSHPort = 22
	d.PrivateIPOnly = flags.Bool("aliyunecs-private-address-only")
	d.InternetMaxBandwidthOut = flags.Int("aliyunecs-internet-max-bandwidth")
	d.InternetChargeType = common.InternetChargeType(flags.String("aliyunecs-internet-charge-type"))
	d.RouteCIDR = flags.String("aliyunecs-route-cidr")
	d.SLBID = flags.String("aliyunecs-slb-id")
	d.DiskSize = flags.Int("aliyunecs-disk-size")
	d.DiskFS = flags.String("aliyunecs-disk-fs")
	d.DiskCategory = ecs.DiskCategory(flags.String("aliyunecs-disk-category"))
	d.ResourceGroupId = flags.String("aliyunecs-resource-group-id")
	tags := flags.StringSlice("aliyunecs-tag")
	//upgradeKernel := false //flags.Bool("aliyunecs-upgrade-kernel")
	//if upgradeKernel {
	//	log.Warnf("%s | The --aliyunecs-upgrade-kernel is deprecated. Please use the Ubuntu 16.04 as the OS image for ECS instance", d.MachineName)
	//}

	ioOptimized := strings.ToLower(flags.String("aliyunecs-io-optimized"))

	d.IoOptimized = (ioOptimized == "true" || ioOptimized == "optimized")
	d.Description = flags.String("aliyunecs-description")
	d.SystemDiskCategory = ecs.DiskCategory(flags.String("aliyunecs-system-disk-category"))
	d.SystemDiskSize = flags.Int("aliyunecs-system-disk-size")

	if d.SystemDiskCategory == "" && d.IoOptimized {
		d.SystemDiskCategory = ecs.DiskCategoryCloudSSD
	}

	if d.DiskCategory == "" && d.IoOptimized {
		d.DiskCategory = ecs.DiskCategoryCloudSSD
	}

	tagMap := make(map[string]string)
	if len(tags) > 0 {
		for _, tag := range tags {
			s := strings.Split(tag, "=")
			if len(s) != 2 {
				log.Infof("%s | Invalid tag for --aliyunecs-tag", tag)
				return fmt.Errorf("%s | Invalid tag for --aliyunecs-tag", tag)
			}
			k := strings.TrimSpace(s[0])
			v := strings.TrimSpace(s[1])
			tagMap[k] = v
		}
	}

	if len(tagMap) > 0 {
		d.Tags = tagMap
	}

	if d.RouteCIDR != "" {
		_, _, err := net.ParseCIDR(d.RouteCIDR)
		if err != nil {
			return fmt.Errorf("%s | Invalid CIDR value for --aliyunecs-route-cidr", d.MachineName)
		}
	}

	if d.InternetMaxBandwidthOut < 0 || d.InternetMaxBandwidthOut > 100 {
		return fmt.Errorf("%s | aliyunecs driver --aliyunecs-internet-max-bandwidth: The value should be in 1 ~ 100", d.MachineName)
	}

	if d.InternetMaxBandwidthOut == 0 {
		d.InternetMaxBandwidthOut = 1
	}

	if d.InternetChargeType != common.PayByTraffic && d.InternetChargeType != common.PayByBandwidth {
		return fmt.Errorf("Unsupported internet charge type: %s", d.InternetChargeType)
	}

	if d.AccessKey == "" {
		return fmt.Errorf("%s | aliyunecs driver requires the --aliyunecs-access-key-id option", d.MachineName)
	}

	if d.SecretKey == "" {
		return fmt.Errorf("%s | aliyunecs driver requires the --aliyunecs-access-key-secret option", d.MachineName)
	}

	//VpcId and VSwitchId are optional or required together
	if (d.VpcId == "" && d.VSwitchId != "") || (d.VpcId != "" && d.VSwitchId == "") {
		return fmt.Errorf("%s | aliyunecs driver requires both the --aliyunecs-vpc-id and --aliyunecs-vswitch-id for Virtual Private Cloud", d.MachineName)
	}

	if d.isSwarmMaster() {
		u, err := url.Parse(d.SwarmHost)
		if err != nil {
			return fmt.Errorf("error parsing swarm host: %s", err)
		}

		parts := strings.Split(u.Host, ":")
		port, err := strconv.Atoi(parts[1])
		if err != nil {
			return err
		}

		swarmPort = port
	}

	if d.APIEndpoint != "" {
		if d.SLBID != "" {
			return fmt.Errorf("Unsupport 'aliyunecs-slb-id' flag when the custom API endpoint is specified")
		}
	}

	if d.DiskFS != "xfs" && d.DiskFS != "ext4" {
		return fmt.Errorf("Unsupport file system for data disk: %s", d.DiskFS)
	}

	if d.SSHPrivateKeyPath == "" && d.SSHKeyPairName != "" {
		return fmt.Errorf("using --aliyunecs-keypair-name also requires --aliyunecs-ssh-keypath")
	}

	return nil
}

func (d *Driver) DriverName() string {
	return driverName
}

func (d *Driver) checkPrereqs() error {

	if d.SLBID != "" {
		loadBalancer, err := d.getSLBClient().DescribeLoadBalancerAttribute(d.SLBID)
		if err != nil {
			return fmt.Errorf("%s | Invalid --aliyunecs-slb-id: %v", d.MachineName, err)
		}
		d.SLBIPAddress = loadBalancer.Address
	}
	return nil
}

func (d *Driver) PreCreateCheck() error {
	return d.checkPrereqs()
}

func (d *Driver) Create() error {

	var (
		err error
	)
	VpcId := d.VpcId
	VSwitchId := d.VSwitchId

	if err := d.checkPrereqs(); err != nil {
		return err
	}

	log.Infof("%s | Creating key pair for instance ...", d.MachineName)

	if err := d.createKeyPair(); err != nil {
		return fmt.Errorf("%s | Failed to create key pair: %v", d.MachineName, err)
	}

	log.Infof("%s | Configuring security groups instance ...", d.MachineName)
	if err := d.configureSecurityGroup(VpcId, d.SecurityGroupName); err != nil {
		return err
	}

	// Create random password if no input
	if d.SSHPassword == "" && d.SSHKeyPairName == "" {
		d.SSHPassword = randomPassword()
		log.Infof("%s | Launching instance with generated password, please update password in console or log in with ssh key.", d.MachineName)
	}

	imageID := d.GetImageID(d.ImageID)
	log.Infof("%s | Creating instance with image %s ...", d.MachineName, imageID)

	ioOptimized := ecs.IoOptimizedNone
	if d.IoOptimized {
		ioOptimized = ecs.IoOptimizedOptimized
	}

	args := ecs.CreateInstanceArgs{
		RegionId:                d.Region,
		InstanceName:            d.GetMachineName(),
		Description:             d.Description,
		ImageId:                 imageID,
		InstanceType:            d.InstanceType,
		SecurityGroupId:         d.SecurityGroupId,
		InternetChargeType:      d.InternetChargeType,
		Password:                d.SSHPassword,
		KeyPairName:             d.SSHKeyPairName,
		VSwitchId:               VSwitchId,
		ZoneId:                  d.Zone,
		IoOptimized:             ioOptimized,
		InternetMaxBandwidthOut: d.InternetMaxBandwidthOut,
		ResourceGroupId: d.ResourceGroupId,
		ClientToken:             d.getClient().GenerateClientToken(),
	}

	if d.SystemDiskCategory != "" {
		args.SystemDisk.Category = d.SystemDiskCategory
	}

	if d.SystemDiskSize > 0 {
		args.SystemDisk.Size = d.SystemDiskSize
	}

	if d.DiskSize > 0 { // Allocate Data Disk

		disk := ecs.DataDiskType{
			DiskName:           d.MachineName + "_data",
			Description:        "Data volume for Docker",
			Size:               d.DiskSize,
			Category:           d.DiskCategory,
			Device:             "/dev/xvdb",
			DeleteWithInstance: true,
		}

		args.DataDisk = []ecs.DataDiskType{disk}

	}

	// Create instance
	instanceId, err := d.getClient().CreateInstance(&args)

	if err != nil {
		err = fmt.Errorf("%s | Failed to create instance: %s", d.MachineName, err)
		log.Error(err)
		return err
	}
	log.Infof("%s | Create instance %s successfully", d.MachineName, instanceId)

	d.InstanceId = instanceId

	// Wait for creation successfully
	err = d.getClient().WaitForInstance(instanceId, ecs.Stopped, timeout)

	if err != nil {
		err = fmt.Errorf("%s | Failed to wait instance to 'stopped': %s", d.MachineName, err)
		log.Error(err)
	}

	if err == nil {
		err = d.configNetwork(VpcId, instanceId)
	}

	if err == nil {
		// Start instance
		log.Infof("%s | Starting instance %s ...", d.MachineName, instanceId)
		err = d.getClient().StartInstance(instanceId)
		if err == nil {
			// Wait for running
			err = d.getClient().WaitForInstance(instanceId, ecs.Running, timeout)

			if err == nil {
				log.Infof("%s | Start instance %s successfully", d.MachineName, instanceId)
				instance, err := d.getInstance()

				if err == nil {
					d.Zone = instance.ZoneId
					d.PrivateIPAddress = d.GetPrivateIP(instance)

					d.IPAddress = d.getIP(instance)

					ssh.SetDefaultClient(ssh.Native)

					d.configECSInstance(imageID)

					log.Infof("%s | Created instance %s successfully with public IP address %s and private IP address %s",
						d.MachineName,
						d.InstanceId,
						d.IPAddress,
						d.PrivateIPAddress,
					)
				}
			} else {
				err = fmt.Errorf("%s | Failed to wait instance to running state: %s", d.MachineName, err)
			}
		} else {
			err = fmt.Errorf("%s | Failed to start instance %s: %v", d.MachineName, instanceId, err)
		}
	}

	// Add instance tags
	if len(d.Tags) > 0 {
		log.Infof("%s | Adding tags %v to instance %s ...", d.MachineName, d.Tags, instanceId)
		args := ecs.AddTagsArgs{
			RegionId:     d.Region,
			ResourceId:   instanceId,
			ResourceType: ecs.TagResourceInstance,
			Tag:          d.Tags,
		}
		err2 := d.getClient().AddTags(&args)
		if err2 != nil {
			log.Warnf("%s | Failed to add tags %v to instance %s: %v", d.MachineName, d.Tags, instanceId, err)
		}
	}

	return err
}

func (d *Driver) configNetwork(vpcId string, instanceId string) error {
	var err error
	if vpcId == "" {
		// Assign public IP if not private IP only

		if !d.PrivateIPOnly {
			// Allocate public IP address for classic network
			var ipAddress string
			ipAddress, err = d.getClient().AllocatePublicIpAddress(instanceId)
			if err != nil {
				err = fmt.Errorf("%s | Error allocate public IP address for instance %s: %v", d.MachineName, instanceId, err)
			} else {
				log.Infof("%s | Allocate publice IP address %s for instance %s successfully", d.MachineName, ipAddress, instanceId)
			}
		}
	} else {
		err := d.addRouteEntry(vpcId)
		if err != nil {
			return err
		}
		if !d.PrivateIPOnly {
			// Create EIP for virtual private cloud
			eipArgs := ecs.AllocateEipAddressArgs{
				RegionId:           d.Region,
				Bandwidth:          d.InternetMaxBandwidthOut,
				InternetChargeType: d.InternetChargeType,
				ClientToken:        d.getClient().GenerateClientToken(),
			}
			log.Infof("%s | Allocating Eip address for instance %s ...", d.MachineName, instanceId)

			_, allocationId, err := d.getClient().AllocateEipAddress(&eipArgs)
			if err != nil {
				return fmt.Errorf("%s | Failed to allocate EIP address: %v", d.MachineName, err)
			}
			err = d.getClient().WaitForEip(d.Region, allocationId, ecs.EipStatusAvailable, 60)
			if err != nil {
				log.Infof("%s | Releasing Eip address %s for ...", d.MachineName, allocationId)
				err2 := d.getClient().ReleaseEipAddress(allocationId)
				if err2 != nil {
					log.Warnf("%s | Failed to release EIP address: %v", d.MachineName, err2)
				}
				return fmt.Errorf("%s | Failed to wait EIP %s: %v", d.MachineName, allocationId, err)
			}
			log.Infof("%s | Associating Eip address %s for instance %s ...", d.MachineName, allocationId, instanceId)
			err = d.getClient().AssociateEipAddress(allocationId, instanceId)
			if err != nil {
				return fmt.Errorf("%s | Failed to associate EIP address: %v", d.MachineName, err)
			}
			err = d.getClient().WaitForEip(d.Region, allocationId, ecs.EipStatusInUse, 60)
			if err != nil {
				return fmt.Errorf("%s | Failed to wait EIP %s: %v", d.MachineName, allocationId, err)
			}
		}
	}

	if d.SLBID != "" { // Add the instance to SLB
		log.Infof("%s | Adding instance %s to SLB %s ...", d.MachineName, instanceId, d.SLBID)
		count := 0
		for {
			backendServers := []slb.BackendServerType{
				slb.BackendServerType{
					ServerId: instanceId,
					Weight:   100,
				},
			}
			_, err = d.getSLBClient().AddBackendServers(d.SLBID, backendServers)
			if err != nil {
				log.Errorf("%s | Failed to add instance to SLB: %v", d.MachineName, err)
				count++
				if count <= maxRetry {
					time.Sleep(time.Duration(5000+mrand.Int63n(2000)) * time.Millisecond)
					continue
				} else {
					return fmt.Errorf("%s | Failed to delete route entry after %d times", d.MachineName, maxRetry)
				}
			}
			break
		}
	}

	return err
}

func (d *Driver) removeRouteEntry(vpcId string, regionId common.Region, instanceId string) error {

	client := d.getClient()

	describeArgs := ecs.DescribeVpcsArgs{
		VpcId:    vpcId,
		RegionId: regionId,
	}

	vpcs, _, err := client.DescribeVpcs(&describeArgs)
	if err != nil {
		return fmt.Errorf("%s | Failed to describe VPC %s in region %s: %v", d.MachineName, d.VpcId, d.Region, err)
	}
	vrouterId := vpcs[0].VRouterId

	describeRouteTablesArgs := ecs.DescribeRouteTablesArgs{
		VRouterId: vrouterId,
	}

	routeTables, _, err := client.DescribeRouteTables(&describeRouteTablesArgs)
	if err != nil {
		return fmt.Errorf("%s | Failed to describe route tables: %v", d.MachineName, err)
	}

	routeEntries := routeTables[0].RouteEntrys.RouteEntry

	// Find route entry associated with instance
	for _, routeEntry := range routeEntries {
		count := 0

		if routeEntry.InstanceId == instanceId {
			for {
				deleteArgs := ecs.DeleteRouteEntryArgs{
					RouteTableId:         routeEntry.RouteTableId,
					DestinationCidrBlock: routeEntry.DestinationCidrBlock,
					NextHopId:            routeEntry.InstanceId,
				}
				log.Infof("%s | Deleting route entry for instance %s ...", d.MachineName, d.InstanceId)

				err := client.DeleteRouteEntry(&deleteArgs)
				if err != nil {
					log.Errorf("%s | Failed to delete route entry: %v", d.MachineName, err)
					count++
					if count <= maxRetry {
						time.Sleep(time.Duration(5000+mrand.Int63n(2000)) * time.Millisecond)
						continue
					} else {
						return fmt.Errorf("%s | Failed to delete route entry after %d times", d.MachineName, maxRetry)
					}
				}
				return nil
			}
		}
	}
	return nil
}

func (d *Driver) addRouteEntry(vpcId string) error {

	if d.RouteCIDR != "" {
		client := d.getClient()

		describeArgs := ecs.DescribeVpcsArgs{
			VpcId:    vpcId,
			RegionId: d.Region,
		}
		vpcs, _, err := client.DescribeVpcs(&describeArgs)
		if err != nil {
			return fmt.Errorf("%s | Failed to describe VPC %s in region %s: %v", d.MachineName, d.VpcId, d.Region, err)
		}
		vrouterId := vpcs[0].VRouterId
		describeVRoutersArgs := ecs.DescribeVRoutersArgs{
			VRouterId: vrouterId,
			RegionId:  d.Region,
		}
		vrouters, _, err := client.DescribeVRouters(&describeVRoutersArgs)
		if err != nil {
			return fmt.Errorf("%s | Failed to describe VRouters: %v", d.MachineName, err)
		}
		routeTableId := vrouters[0].RouteTableIds.RouteTableId[0]
		count := 0

		for {
			createArgs := ecs.CreateRouteEntryArgs{
				RouteTableId:         routeTableId,
				DestinationCidrBlock: d.RouteCIDR,
				NextHopType:          ecs.NextHopInstance,
				NextHopId:            d.InstanceId,
				ClientToken:          client.GenerateClientToken(),
			}
			err = client.CreateRouteEntry(&createArgs)
			if err == nil {
				break
			}

			ecsErr, _ := err.(*common.Error)
			//Retry for IncorretRouteEntryStatus or Internal Error
			if ecsErr != nil && (ecsErr.StatusCode == 500 || (ecsErr.StatusCode == 400 && ecsErr.Code == "IncorrectRouteEntryStatus")) {
				count++
				if count <= maxRetry {
					time.Sleep(time.Duration(5000+mrand.Int63n(2000)) * time.Millisecond)
					continue
				}

			}
			return fmt.Errorf("%s | Failed to create route entry: %v", d.MachineName, err)
		}
	}
	return nil
}

func (d *Driver) GetURL() (string, error) {
	ip, err := d.GetIP()
	if err != nil {
		return "", err
	}
	if ip == "" {
		return "", nil
	}
	return fmt.Sprintf("tcp://%s:%d", ip, dockerPort), nil
}

func (d *Driver) GetIP() (string, error) {
	inst, err := d.getInstance()
	if err != nil {
		return "", err
	}

	return d.getIP(inst), nil
}

func (d *Driver) GetPrivateIP(inst *ecs.InstanceAttributesType) string {
	if inst.InnerIpAddress.IpAddress != nil && len(inst.InnerIpAddress.IpAddress) > 0 {
		return inst.InnerIpAddress.IpAddress[0]
	}

	if inst.VpcAttributes.PrivateIpAddress.IpAddress != nil && len(inst.VpcAttributes.PrivateIpAddress.IpAddress) > 0 {
		return inst.VpcAttributes.PrivateIpAddress.IpAddress[0]
	}
	return ""
}

func (d *Driver) getIP(inst *ecs.InstanceAttributesType) string {
	if d.PrivateIPOnly {
		return d.GetPrivateIP(inst)
	}
	if inst.PublicIpAddress.IpAddress != nil && len(inst.PublicIpAddress.IpAddress) > 0 {
		return inst.PublicIpAddress.IpAddress[0]
	}
	if len(inst.EipAddress.IpAddress) > 0 {
		return inst.EipAddress.IpAddress
	}
	return ""
}

func (d *Driver) GetState() (state.State, error) {
	inst, err := d.getInstance()
	if err != nil {
		return state.Error, err
	}
	switch ecs.InstanceStatus(inst.Status) {
	case ecs.Starting:
		return state.Starting, nil
	case ecs.Running:
		return state.Running, nil
	case ecs.Stopping:
		return state.Stopping, nil
	case ecs.Stopped:
		return state.Stopped, nil
	default:
		return state.Error, nil
	}
}

func (d *Driver) GetSSHHostname() (string, error) {
	return d.GetIP()
}

func (d *Driver) Start() error {
	if err := d.getClient().StartInstance(d.InstanceId); err != nil {
		log.Errorf("%s | Failed to start instance %s: %v", d.MachineName, d.InstanceId, err)
		return err
	}

	// Wait for running
	err := d.getClient().WaitForInstance(d.InstanceId, ecs.Running, timeout)

	if err != nil {
		log.Errorf("%s | Failed to wait instance %s running: %v", d.MachineName, d.InstanceId, err)
		return err
	}

	return nil
}

func (d *Driver) Stop() error {
	if err := d.getClient().StopInstance(d.InstanceId, false); err != nil {
		log.Errorf("%s | Failed to stop instance %s: %v", d.MachineName, d.InstanceId, err)
		return err
	}

	// Wait for stopped
	err := d.getClient().WaitForInstance(d.InstanceId, ecs.Stopped, timeout)

	if err != nil {
		log.Errorf("%s | Failed to wait instance %s stopped: %v", d.MachineName, d.InstanceId, err)
		return err
	}

	return nil
}

func (d *Driver) Remove() error {
	log.Infof("%s | Remove instance %s ...", d.MachineName, d.InstanceId)

	if d.InstanceId == "" {
		return fmt.Errorf("%s | Unknown instance id", d.MachineName)
	}

	s, err := d.GetState()
	if err == nil && s == state.Running {
		if err := d.Stop(); err != nil {
			log.Errorf("%s | Unable to removed the instance %s: %s", d.MachineName, d.InstanceId, err)
		}
	}

	instance, err := d.getInstance()
	if err != nil {
		log.Errorf("%s | Unable to describe the instance %s: %s", d.MachineName, d.InstanceId, err)
	} else {
		// Check and release EIP if exists
		if len(instance.EipAddress.AllocationId) != 0 {

			allocationId := instance.EipAddress.AllocationId

			err = d.getClient().UnassociateEipAddress(allocationId, instance.InstanceId)
			if err != nil {
				log.Errorf("%s | Failed to unassociate EIP address from instance %s: %v", d.MachineName, d.InstanceId, err)
			}
			err = d.getClient().WaitForEip(instance.RegionId, allocationId, ecs.EipStatusAvailable, 0)
			if err != nil {
				log.Errorf("%s | Failed to wait EIP %s available: %v", d.MachineName, allocationId, err)
			}
			err = d.getClient().ReleaseEipAddress(allocationId)
			if err != nil {
				log.Errorf("%s | Failed to release EIP address: %v", d.MachineName, err)
			}
		}
		log.Debugf("%s | instance.VpcAttributes: %++v\n", d.MachineName, instance.VpcAttributes)

		vpcId := instance.VpcAttributes.VpcId
		if vpcId != "" {
			// Remove route entry firstly
			d.removeRouteEntry(vpcId, instance.RegionId, instance.InstanceId)
		}
	}

	log.Infof("%s | Deleting instance: %s", d.MachineName, d.InstanceId)
	if err := d.getClient().DeleteInstance(d.InstanceId); err != nil {
		return fmt.Errorf("%s | Unable to delete instance %s: %s", d.MachineName, d.InstanceId, err)
	}
	d.InstanceId = ""
	d.IPAddress = ""
	d.PrivateIPAddress = ""
	d.Zone = ""
	return nil
}

func (d *Driver) Restart() error {
	if err := d.getClient().RebootInstance(d.InstanceId, false); err != nil {
		return fmt.Errorf("%s | Unable to restart instance %s: %s", d.MachineName, d.InstanceId, err)
	}
	return nil
}

func (d *Driver) Kill() error {
	log.Debugf("%s | Killing instance ...", d.MachineName)

	if err := d.getClient().StopInstance(d.InstanceId, true); err != nil {
		return fmt.Errorf("%s | Unable to kill instance %s: %s", d.MachineName, d.InstanceId, err)
	}
	return nil
}

func (d *Driver) getSLBClient() *slb.Client {
	if d.slbClient == nil {
		client := slb.NewClient(d.AccessKey, d.SecretKey)
		client.SetDebug(false)
		d.slbClient = client
	}
	return d.slbClient
}

func (d *Driver) getClient() *ecs.Client {
	if d.client == nil {
		client := ecs.NewClient(d.AccessKey, d.SecretKey)
		if d.APIEndpoint != "" {
			client.SetEndpoint(d.APIEndpoint)
		}
		client.SetUserAgent("AliyunContainerService/docker-machine")
		client.SetDebug(false)
		d.client = client
	}
	return d.client
}

func (d *Driver) getInstance() (*ecs.InstanceAttributesType, error) {
	return d.getClient().DescribeInstanceAttribute(d.InstanceId)
}

func (d *Driver) createKeyPair() error {

	if d.SSHPrivateKeyPath == "" {
		log.Debugf("%s | SSH key path: %s", d.MachineName, d.GetSSHKeyPath())

		if err := ssh.GenerateSSHKey(d.GetSSHKeyPath()); err != nil {
			return err
		}

		publicKey, err := ioutil.ReadFile(d.GetSSHKeyPath() + ".pub")
		if err != nil {
			return err
		}

		d.PublicKey = publicKey
	} else {
		log.Debugf("%s | Using SSHPrivateKeyPath: %s", d.MachineName, d.SSHPrivateKeyPath)
		if err := mcnutils.CopyFile(d.SSHPrivateKeyPath, d.GetSSHKeyPath()); err != nil {
			return err
		}
		if err := mcnutils.CopyFile(d.SSHPrivateKeyPath+".pub", d.GetSSHKeyPath()+".pub"); err != nil {
			return err
		}
		if d.SSHKeyPairName != "" {
			log.Debugf("%s | Using existing ECS key pair: %s", d.MachineName, d.SSHKeyPairName)
			return nil
		}
	}

	return nil
}

func (d *Driver) isSwarmMaster() bool {
	return d.SwarmMaster
}

func (d *Driver) getSecurityGroup(id string) (sg *ecs.DescribeSecurityGroupAttributeResponse, err error) {
	args := ecs.DescribeSecurityGroupAttributeArgs{
		SecurityGroupId: id,
		RegionId:        d.Region,
	}
	return d.getClient().DescribeSecurityGroupAttribute(&args)
}

func (d *Driver) securityGroupAvailableFunc(id string) func() bool {
	return func() bool {
		_, err := d.getSecurityGroup(id)
		if err == nil {
			return true
		}
		log.Debug(err)
		return false
	}
}

func (d *Driver) configureSecurityGroup(vpcId string, groupName string) error {
	log.Debugf("%s | Configuring security group in %s", d.MachineName, d.VpcId)

	var securityGroup *ecs.DescribeSecurityGroupAttributeResponse

	args := ecs.DescribeSecurityGroupsArgs{
		RegionId: d.Region,
		VpcId:    vpcId,
	}

	for {
		groups, pagination, err := d.getClient().DescribeSecurityGroups(&args)
		if err != nil {
			return err
		}
		//log.Debugf("DescribeSecurityGroups: %++v\n", groups)

		for _, grp := range groups {
			if grp.SecurityGroupName == groupName && grp.VpcId == d.VpcId {
				log.Debugf("%s | Found existing security group (%s) in %s", d.MachineName, groupName, d.VpcId)
				securityGroup, _ = d.getSecurityGroup(grp.SecurityGroupId)
				break
			}
		}

		if securityGroup != nil {
			break
		}

		nextPage := pagination.NextPage()
		if nextPage == nil {
			break
		}
		args.Pagination = *nextPage
	}

	// if not found, create
	if securityGroup == nil {
		log.Debugf("%s | Creating security group (%s) in %s", d.MachineName, groupName, d.VpcId)
		creationArgs := ecs.CreateSecurityGroupArgs{
			RegionId:          d.Region,
			SecurityGroupName: groupName,
			Description:       "Docker Machine",
			VpcId:             vpcId,
			ClientToken:       d.getClient().GenerateClientToken(),
		}

		groupId, err := d.getClient().CreateSecurityGroup(&creationArgs)
		if err != nil {
			return err
		}

		// wait until created (dat eventual consistency)
		log.Debugf("%s | Waiting for group (%s) to become available", d.MachineName, groupId)
		if err := mcnutils.WaitFor(d.securityGroupAvailableFunc(groupId)); err != nil {
			return err
		}
		securityGroup, err = d.getSecurityGroup(groupId)
		if err != nil {
			return err
		}
	}

	d.SecurityGroupId = securityGroup.SecurityGroupId

	perms := d.configureSecurityGroupPermissions(securityGroup)

	for _, permission := range perms {
		log.Debugf("%s | Authorizing group %s with permission: %v", d.MachineName, securityGroup.SecurityGroupName, permission)
		args := permission.createAuthorizeSecurityGroupArgs(d.Region, d.SecurityGroupId)
		args.NicType = ecs.NicTypeInternet
		if err := d.getClient().AuthorizeSecurityGroup(args); err != nil {
			log.Warnf("%s | Failed to authorizing group %s with permission: %v", d.MachineName, securityGroup.SecurityGroupName, permission, err)
			return err
		}
		args.NicType = ecs.NicTypeIntranet
		//如果是经典网络,则需要去掉2376的内网入规则
		if (d.VpcId == "" && d.VSwitchId == "") && permission.FromPort != dockerPort && permission.ToPort != dockerPort {
			if err := d.getClient().AuthorizeSecurityGroup(args); err != nil {
				log.Warnf("%s | Failed to authorizing group %s with permission: %v", d.MachineName, securityGroup.SecurityGroupName, permission, err)
				return err
			}
		}
	}

	return nil
}

type IpPermission struct {
	IpProtocol ecs.IpProtocol
	FromPort   int
	ToPort     int
	IpRange    string
}

func (p *IpPermission) createAuthorizeSecurityGroupArgs(regionId common.Region, securityGroupId string) *ecs.AuthorizeSecurityGroupArgs {
	args := ecs.AuthorizeSecurityGroupArgs{
		RegionId:        regionId,
		SecurityGroupId: securityGroupId,
		IpProtocol:      p.IpProtocol,
		SourceCidrIp:    p.IpRange,
		PortRange:       fmt.Sprintf("%d/%d", p.FromPort, p.ToPort),
	}
	return &args
}

func (d *Driver) configureSecurityGroupPermissions(group *ecs.DescribeSecurityGroupAttributeResponse) []IpPermission {
	hasSSHPort := false
	hasDockerPort := false
	for _, p := range group.Permissions.Permission {
		portRange := strings.Split(p.PortRange, "/")

		log.Debugf("%s | portRange %v", d.MachineName, portRange)
		fromPort, _ := strconv.Atoi(portRange[0])
		switch fromPort {
		case 22:
			hasSSHPort = true
		case dockerPort:
			hasDockerPort = true
		}
	}

	perms := []IpPermission{}

	if !hasSSHPort {
		perms = append(perms, IpPermission{
			IpProtocol: ecs.IpProtocolTCP,
			FromPort:   22,
			ToPort:     22,
			IpRange:    ipRange,
		})
	}

	if !hasDockerPort {
		perms = append(perms, IpPermission{
			IpProtocol: ecs.IpProtocolTCP,
			FromPort:   dockerPort,
			ToPort:     dockerPort,
			IpRange:    ipRange,
		})
	}

	//80
	perms = append(perms, IpPermission{
		IpProtocol: ecs.IpProtocolTCP,
		FromPort:   80,
		ToPort:     80,
		IpRange:    ipRange,
	})

	//443
	perms = append(perms, IpPermission{
		IpProtocol: ecs.IpProtocolTCP,
		FromPort:   443,
		ToPort:     443,
		IpRange:    ipRange,
	})

	//ICMP
	perms = append(perms, IpPermission{
		IpProtocol: ecs.IpProtocolICMP,
		FromPort:   -1,
		ToPort:     -1,
		IpRange:    ipRange,
	})

	//如果是容器网段的话,需要设置容器网段开放安全组
	if d.VpcId != "" || d.VSwitchId != "" {
		containerIPRange, err := getContainerCIDR(d.RouteCIDR)
		if err == nil {
			perms = append(perms, IpPermission{
				IpProtocol: ecs.IpProtocolAll,
				FromPort:   -1,
				ToPort:     -1,
				IpRange:    containerIPRange,
			})
		} else {
			log.Errorf("%s failed to get container bip %++v", group.SecurityGroupId, err)
		}
	}

	log.Debugf("%s | Configuring new permissions: %v", d.MachineName, perms)

	return perms
}

func getContainerCIDR(cidrBlock string) (string, error) {
	ip, _, err := net.ParseCIDR(cidrBlock)
	if err != nil {
		return "", err
	}

	ip = ip.To4()
	ip[2] = 0
	ip[3] = 0

	return fmt.Sprintf("%s/16", ip.String()), nil
}

func (d *Driver) deleteSecurityGroup() error {
	log.Infof("%s | Deleting security group %s", d.MachineName, d.SecurityGroupId)
	if err := d.getClient().DeleteSecurityGroup(d.Region, d.SecurityGroupId); err != nil {
		return err
	}

	return nil
}

func generateId() string {
	rb := make([]byte, 10)
	_, err := rand.Read(rb)
	if err != nil {
		log.Errorf("Unable to generate id: %s", err)
	}

	h := md5.New()
	io.WriteString(h, string(rb))
	return fmt.Sprintf("%x", h.Sum(nil))
}

func (d *Driver) configECSInstance(imageId string) error {
	ipAddr := d.IPAddress
	port, _ := d.GetSSHPort()
	tcpAddr := fmt.Sprintf("%s:%d", ipAddr, port)

	log.Infof("%s | Waiting SSH service %s is ready to connect ...", d.MachineName, tcpAddr)

	log.Infof("%s | Uploading SSH keypair to %s ...", d.MachineName, tcpAddr)

	var auth *ssh.Auth

	if d.SSHPrivateKeyPath == "" {
		auth = &ssh.Auth{
			Passwords: []string{d.SSHPassword},
		}
	} else {
		auth = &ssh.Auth{
			Keys: []string{d.SSHPrivateKeyPath},
		}
	}

	sshClient, err := ssh.NewClient(d.GetSSHUsername(), ipAddr, port, auth)

	if err != nil {
		return err
	}

	if d.SSHKeyPairName == "" {
		err = d.uploadKeyPair(sshClient)
		if err != nil {
			return err
		}
	}

	if isUbuntuImage(imageId) {
		d.fixAptConf(sshClient)
	}

	d.fixRoutingRules(sshClient)

	if d.DiskSize > 0 {
		d.autoFdisk(sshClient)
	}

	return nil
}

func (d *Driver) uploadKeyPair(sshClient ssh.Client) error {
	command := fmt.Sprintf("mkdir -p ~/.ssh; echo '%s' > ~/.ssh/authorized_keys", string(d.PublicKey))

	log.Debugf("%s | Upload the public key with command: %s", d.MachineName, command)

	output, err := sshClient.Output(command)

	log.Debugf("%s | Upload command err, output: %v: %s", d.MachineName, err, output)

	return err
}

func (d *Driver) fixAptConf(sshClient ssh.Client) {
	output, err := sshClient.Output("sed -i 's/Acquire::http::Proxy/#Acquire::http::Proxy/' /etc/apt/apt.conf")
	log.Debugf("%s | Update the apt.conf command err, output: %v: %s", d.MachineName, err, output)
}

// Fix the routing rules
func (d *Driver) fixRoutingRules(sshClient ssh.Client) {
	output, err := sshClient.Output("route del -net 172.16.0.0/12")
	log.Debugf("%s | Delete route command err, output: %v: %s", d.MachineName, err, output)

	output, err = sshClient.Output("if [ -e /etc/network/interfaces ]; then sed -i '/^up route add -net 172.16.0.0 netmask 255.240.0.0 gw/d' /etc/network/interfaces; fi")
	log.Debugf("%s | Fix route in /etc/network/interfaces command err, output: %v: %s", d.MachineName, err, output)

	output, err = sshClient.Output("if [ -e /etc/sysconfig/network-scripts/route-eth0 ]; then sed -i '/^172.16.0.0\\/12 via /d' /etc/sysconfig/network-scripts/route-eth0; fi")
	log.Debugf("%s | Fix route in /etc/sysconfig/network-scripts/route-eth0 command err, output: %v: %s", d.MachineName, err, output)
}

// Mount the addtional disk
func (d *Driver) autoFdisk(sshClient ssh.Client) {

	s := autoFdiskScriptExt4

	if d.DiskFS == "xfs" {
		s = autoFdiskScriptXFS
	}

	script := fmt.Sprintf("cat > ~/machine_autofdisk.sh <<MACHINE_EOF\n%s\nMACHINE_EOF\n", s)
	output, err := sshClient.Output(script)
	output, err = sshClient.Output("bash ~/machine_autofdisk.sh")
	log.Debugf("%s | Auto Fdisk command err, output: %v: %s", d.MachineName, err, output)
}